新来个技术总监,禁止我们使用Lombok!
The following article comes from Java之道 Author Hollis
我有个学弟,在一家小型互联网公司做 Java 后端开发,最近他们公司新来了一个技术总监。
这位技术总监对技术细节很看重,一来公司之后就推出了很多"政策",比如定义了很多开发规范、日志规范、甚至是要求大家统一使用某一款 IDE。
但是这些都不是我这个学弟和我吐槽的点,他真正和我吐槽的是,他很不能理解,这位新来的技术总监竟然禁止公司内部所有开发使用 Lombok。但是又没给出十分明确的,可以让人信服的理由。
于是他来找我聊天,问我这个要求到底是否合理。关于这个事情,我认为这位技术总监的出发点是好的,但是做法未免有些极端。
之所以说出发点是好的,是因为使用 Lombok 确实会带来很多问题,而且我个人在工作中也基本不主动使用。
之所以说不主动使用,那是因为有些同事的代码还是使用了的,所以我也被迫的要安装 Lombok 的插件。
既然聊到这个话题,就简单说说我的一些看法。
Lombok 有什么好处?
Lombok 是一款非常实用 Java 工具,可用来帮助开发人员消除 Java 的冗长代码,尤其是对于简单的 Java 对象(POJO)。它通过注释实现这一目的。
如果大家对于 Lombok 比较了解的话,可以先跳过这一段,直接往后看,如果不是很熟悉的话,可以简单了解一下。
想在项目中使用 Lombok,需要三个步骤:
①IDE 中安装 Lombok 插件
目前 Lombok 支持多种 IDE,其中包括主流的 Eclipse、Intellij IDEA、Myeclipse 等都是支持的。
在 IDEA 中安装方式如下:
②导入相关依赖
Lombok 支持使用多重构建工具进行导入依赖,目前主要支持 maven、gardle、ant 等。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
③代码中使用注解
Lombok 精简代码的方式主要是通过注解来实现,其中常用的有 @Data、@Getter/@Setter、@Builder、@NonNull 等。
import lombok.Data;
@Data
public class Menu {
private String shopId;
private String skuMenuId;
private String skuName;
}
使用 @Data 注解在类上,相当于同时使用了 @ToString、@EqualsAndHashCode、@Getter、@Setter 和 @RequiredArgsConstrutor 这些注解,对于 POJO 类十分有用。
即自动帮忙给例子中的 Menu 类中定义了 toString、Getter、Setter 等方法。
通过上面的例子,大家可以发现,我们使用 @Data 注解大大减少了代码量,使代码非常简洁。这也是很多开发者热衷于使用 Lombok 的主要原因。
另外,关于 Lombok 的使用,不同人有不同的看法,因为很多人都使用过 Lombok,对于他的优点都比较了解,所以接下来我们重点说一下 Lombok 的使用会带来哪些问题。
Lombok 有什么坏处?
强 X 队友
因为 Lombok 的使用要求开发者一定要在 IDE 中安装对应的插件。
如果未安装插件的话,使用 IDE 打开一个基于 Lombok 的项目的话会提示找不到方法等错误。导致项目编译失败。
也就是说,如果项目组中有一个人使用了 Lombok,那么其他人就必须也要安装 IDE 插件。否则就没办法协同开发。
更重要的是,如果我们定义的一个 jar 包中使用了 Lombok,那么就要求所有依赖这个 jar 包的所有应用都必须安装插件,这种侵入性是很高的。
代码可读性,可调试性低
在代码中使用了 Lombok,确实可以帮忙减少很多代码,因为 Lombok 会帮忙自动生成很多代码。
但是这些代码是要在编译阶段才会生成的,所以在开发的过程中,其实很多代码是缺失的。
在代码中大量使用 Lombok,就导致代码的可读性会低很多,而且也会给代码调试带来一定的问题。
比如,我们想要知道某个类中的某个属性的 getter 方法都被哪些类引用的话,就没那么简单了。
有坑
因为 Lombok 使代码开发非常简便,这就使得部分开发者对其产生过度依赖。
在使用 Lombok 过程中,如果对于各种注解的底层原理不理解的话,很容易产生意想不到的结果。
举一个简单的例子,我们知道,当我们使用 @Data 定义一个类的时候,会自动帮我们生成 equals() 方法 。
但是如果只使用了 @Data,而不使用 @EqualsAndHashCode(callSuper=true) 的话,会默认是 @EqualsAndHashCode(callSuper=false)。
这时候生成的 equals() 方法只会比较子类的属性,不会考虑从父类继承的属性,无论父类属性访问权限是否开放。这就可能得到意想不到的结果。
影响升级
因为 Lombok 对于代码有很强的侵入性,就可能带来一个比较大的问题,那就是会影响我们对 JDK 的升级。
按照如今 JDK 的升级频率,每半年都会推出一个新的版本,但是 Lombok 作为一个第三方工具,并且是由开源团队维护的,那么他的迭代速度是无法保证的。
所以,如果我们需要升级到某个新版本的 JDK 的时候,若其中的特性在 Lombok 中不支持的话就会受到影响。
还有一个可能带来的问题,就是 Lombok 自身的升级也会受到限制。
因为一个应用可能依赖了多个 jar 包,而每个 jar 包可能又要依赖不同版本的 Lombok。
这就导致在应用中需要做版本仲裁,而我们知道,jar 包版本仲裁是没那么容易的,而且发生问题的概率也很高。
破坏封装性
以上几个问题,我认为都是有办法可以避免的。但是有些人排斥使用 Lombok 还有一个重要的原因,那就是他会破坏封装性。
众所周知,Java 的三大特性包括封装性、继承性和多态性。
如果我们在代码中直接使用 Lombok,那么他会自动帮我们生成 getter、setter 等方法,这就意味着,一个类中的所有参数都自动提供了设置和读取方法。
@Data
public class ShoppingCart {
//商品数目
private int itemsCount;
//总价格
private double totalPrice;
//商品明细
private List items = new ArrayList<>();
}
我们知道,购物车中商品数目、商品明细以及总价格三者之前其实是有关联关系的,如果需要修改的话是要一起修改的。
但是,我们使用了 Lombok 的 @Data 注解,对于 itemsCount 和 totalPrice 这两个属性,虽然我们将它们定义成 private 类型,但是提供了 public 的 getter、setter 方法。
外部可以通过 setter 方法随意地修改这两个属性的值。我们可以随意调用 setter 方法,来重新设置 itemsCount、totalPrice 属性的值,这也会导致其跟 items 属性的值不一致。
而面向对象封装的定义是:通过访问权限控制,隐藏内部数据,外部仅能通过类提供的有限的接口访问、修改内部数据。所以,暴露不应该暴露的 setter 方法,明显违反了面向对象的封装特性。
好的做法应该是不提供 getter/setter,而是只提供一个 public 的 addItem 方法,同时去修改 itemsCount、totalPrice 以及 items 三个属性。
总结
本文总结了常用的 Java 开发工具 Lombok 的优缺点。
优点是使用注解即可帮忙自动生成代码,大大减少了代码量,使代码非常简洁。
但是并不意味着 Lombok 的使用没有任何问题,在使用 Lombok 的过程中,还可能存在对队友不友好、对代码不友好、对调试不友好、对升级不友好等问题。
最重要的是,使用 Lombok 还会导致破坏封装性的问题。虽然使用 Lombok 存在着很多方便,但是也带来了一些问题。
但是到底建不建议在日常开发中使用,我其实保持一个中立的态度,不建议大家过度依赖,也不要求大家一定要彻底不用。
只要大家在使用的过程中,或者评估要不要在代码中引入 Lombok 之前,在想到他的优点的同时,能够考虑到他给代码带来的问题的,那么本文的目的也就达到了!
作者:Hollis
简介:一个对 Coding 有着独特追求的人,现任阿里巴巴技术专家,个人技术博主,技术文章全网阅读量数千万,《程序员的三门课》联合作者。
编辑:陶家龙、孙淑娟
出处:转载自微信公众号Java之道(ID:javaways)
精彩文章推荐: